﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace TinyPG
{
    class ParseTreeEval:ParseTree
    {
        public override ParseNode CreateNode(Token token, string text)
        {
            ParseTreeEval node = new ParseTreeEval();
            node.Token = token;
            node.text = text;
            node.Parent = this;
            return node;
        }

        protected override object EvalStart(ParseTree tree, params object[] paramlist)
        {
            int i = 0;
            while (this.GetValue(tree, TokenType.RechEtape, i) != null) { i++; } i = 0;
            while (this.GetValue(tree, TokenType.RechEntree, i) != null) { i++; } i = 0;
            while (this.GetValue(tree, TokenType.RechSortie, i) != null) { i++; } i = 0;
            while (this.GetValue(tree, TokenType.RechTimer, i) != null) { i++; } i = 0;
            while (this.GetValue(tree, TokenType.RechMemoire, i) != null) { i++; } i = 0;
            this.GetValue(tree, TokenType.RechTransition, i);
            this.GetValue(tree, TokenType.StructureG7, i) ;
            this.GetValue(tree, TokenType.ActionSortie, i) ;

            return "";
        }

        protected override object EvalRechEtape(ParseTree tree, params object[] paramlist)
        {
            int i = 0;
            while (this.GetValue(tree, TokenType.DeclarationEtape, i) != null){ i++; }

            return "";
        }

        protected override object EvalDeclarationEtape(ParseTree tree, params object[] paramlist)
        {
            string IdEtape = this.GetValue(tree, TokenType.NumEtape, 0).ToString().Replace("e","");
 
            bool IsInit = false;
            InOut NumEtape = new InOut("ETAPE", Document.Doc.nextEtapeByte, Document.Doc.nextEtapeBit++, false);

            Document.Doc.nextEtapeByte += Document.Doc.nextEtapeBit / 8;
            Document.Doc.nextEtapeBit = Document.Doc.nextEtapeBit % 8;

            if (this.GetValue(tree, TokenType.EtapeInit, 0) != null)
            {
                Document.Doc.Setup_Init_Etapes += "\tset_Bit(tab_etape," + NumEtape.GetByte() + "," + NumEtape.GetBit() + ", 1 );\r\n";
                IsInit = true;
            }
            
            Etape E = new Etape(NumEtape, IsInit, IdEtape);
            if (!IsInit)
            {
                E.SetRangH(-1);
            }

            Document.Doc.DicoEtape.Add(this.GetValue(tree, TokenType.NumEtape, 0).ToString(), E);
            

            return "";
        }

        protected override object EvalRechTimer(ParseTree tree, params object[] paramlist)
        {
            int i = 0;
            while (this.GetValue(tree, TokenType.DeclarationTimer, i) != null) {i++; }
            return "";
        }

        protected override object EvalDeclarationTimer(ParseTree tree, params object[] paramlist)
        {
            
            int Duree;
            Int32.TryParse(this.GetValue(tree, TokenType.Temps, 0).ToString(),out Duree);
            Timer T = new Timer(this.GetValue(tree, TokenType.NumTimer,0).ToString(), Duree);

            Document.Doc.DicoEtape[this.GetValue(tree, TokenType.NumEtape, 0).ToString()].AddTimer(T);

            Document.Doc.Dec_Var_Timers += "//------------Variables Timer " + T.ToString() + "\r\n";
            Document.Doc.Dec_Var_Timers += "int var" + T.ToString() + ";\r\n";
            Document.Doc.Dec_Var_Timers += "int Enable" + this.GetValue(tree, TokenType.NumTimer, 0).ToString() + ";\r\n";

            Document.Doc.GestionInterruption_DecVar += "\tif(var" + T.ToString() + " >0)\r\n\t{\r\n";
            Document.Doc.GestionInterruption_DecVar += "\t\tvar" + T.ToString() + " = var" + T.ToString() + "-1;\r\n\t}\r\n";

            Document.Doc.Setup_Init_Timers += "\tvar" + T.ToString() + "= 0;\r\n";

            if (Document.Doc.DicoEtape[this.GetValue(tree, TokenType.NumEtape, 0).ToString()].GetInit())
            {
                Document.Doc.Setup_Init_InitTimer += "\tvar" + T.ToString() + "=" + T.GetDuree().ToString() + ";\r\n";
                Document.Doc.Setup_Init_EnaInitTimer += "\tEnable" + T.ToString() + "=1;\r\n";
            }
            return "";
        }

        protected override object EvalRechTransition(ParseTree tree, params object[] paramlist)
        {
            int i = 0;
            Document.Doc._listeRecep.Add(i.ToString());
            Document.Doc._listeEquaAssocie.Add(i.ToString());
            while (this.GetValue(tree, TokenType.AffecTransition, i) != null) 
            {
                i++;
                Document.Doc._listeRecep.Add(i.ToString());
                Document.Doc._listeEquaAssocie.Add(i.ToString()); 
            }
            return "";
        }

        protected override object EvalAffecTransition(ParseTree tree, params object[] paramlist)
        {
            Document.Doc._listeRecep.Add(this.GetValue(tree, TokenType.NumTransition, 0).ToString());

            Receptivite R = new Receptivite(this.GetValue(tree, TokenType.NumTransition, 0).ToString());

            Document.Doc.DicoRecep.Add(this.GetValue(tree, TokenType.NumTransition, 0).ToString(), R);

            Document.Doc.Dec_Var_Receptivites += "volatile int ";
            Document.Doc.Dec_Var_Receptivites += this.GetValue(tree, TokenType.NumTransition, 0).ToString();
            Document.Doc.Dec_Var_Receptivites += " =0;\r\n";

            Document.Doc.DefFct_StructureG7_ANTIINFINI += this.GetValue(tree, TokenType.NumTransition, 0).ToString() + " & ";
            Document.Doc.DefFct_StructureG7_MAJReceptivites += "\t\t" + this.GetValue(tree, TokenType.NumTransition, 0).ToString() + "=";
            int i = 0;

             
            while (this.GetValue(tree, TokenType.EquaRecept, i) != null)
            {
                R.MAJEquation(this.GetValue(tree, TokenType.EquaRecept, i).ToString());
                Document.Doc.DefFct_StructureG7_MAJReceptivites += this.GetValue(tree, TokenType.EquaRecept, i).ToString();

                i++;
            }
            Document.Doc.DefFct_StructureG7_MAJReceptivites += " ;\r\n";
            return "";
        }

        protected override object EvalEquaRecept(ParseTree tree, params object[] paramlist)
        {
            string Equation = "";
            if (this.GetValue(tree, TokenType.CaracRECEPT, 0) != null)
            {
                Equation += this.GetValue(tree, TokenType.CaracRECEPT, 0).ToString();
                Document.Doc._listeEquaAssocie.Add(this.GetValue(tree, TokenType.CaracRECEPT, 0).ToString());
            }
            else if (this.GetValue(tree, TokenType.NumTimer, 0) != null)
            {

                string NomTimer = this.GetValue(tree, TokenType.NumTimer, 0).ToString();
                if (this.GetValue(tree, TokenType.OFF, 0) != null)
                {
                    Equation += " (!var" + NomTimer + " & Enable" + NomTimer + ") ";
                    Document.Doc._listeEquaAssocie.Add("/");
                }
                else
                {
                    Equation += " (var" + NomTimer + " & Enable" + NomTimer + ") ";
                }
                Document.Doc._listeEquaAssocie.Add(NomTimer);
            }
            else
            {
                string type = "";
                int numByte = 0, numBit = 0;


                if (this.GetValue(tree, TokenType.NumEntree, 0) != null)
                {
                    Document.Doc._listeEquaAssocie.Add(this.GetValue(tree, TokenType.NumEntree, 0).ToString());
                    type = "ENTREE";
                    InOut E = Document.Doc.DicoInOut[this.GetValue(tree, TokenType.NumEntree, 0).ToString()];
                    numBit = E.GetBit();
                    numByte = E.GetByte();
                }
                else if (this.GetValue(tree, TokenType.NumEtape, 0) != null)
                {
                    Document.Doc._listeEquaAssocie.Add(this.GetValue(tree, TokenType.NumEtape, 0).ToString());
                    type = "ETAPE";
                    Etape E = Document.Doc.DicoEtape[this.GetValue(tree, TokenType.NumEtape, 0).ToString()];
                    numBit = E.GetNumEtape().GetBit();
                    numByte = E.GetNumEtape().GetByte();
                }
                else if (this.GetValue(tree, TokenType.NumMem, 0) != null)
                {
                    Document.Doc._listeEquaAssocie.Add(this.GetValue(tree, TokenType.NumMem, 0).ToString());
                    type = "MEMOIRE";
                    numBit = 0;
                    numByte = Document.Doc.dicoMem[this.GetValue(tree, TokenType.NumMem, 0).ToString()];
                }
            
            
                if (this.GetValue(tree, TokenType.FrontMontant, 0) != null )
                {
                    Document.Doc._listeEquaAssocie.Add("↑");
                    Equation += " FrontMont(";
                    Equation += type + ", " + numByte + ", " + numBit + ") ";                    
                }
                else if (this.GetValue(tree, TokenType.FrontDescendant, 0) != null)
                {
                    Document.Doc._listeEquaAssocie.Add("↓");
                    Equation += " FrontDesc(";
                    Equation += type + ", " + numByte + ", " + numBit + ") ";
                }
                else
                {
                    if (this.GetValue(tree, TokenType.NumEntree, 0) != null)
                        Equation += " get_Bit(CopyPIN," + numByte + ", " + numBit + ") ";
                    if (this.GetValue(tree, TokenType.NumEtape, 0) != null)
                        Equation += " get_Bit(Etat_fin," + numByte + ", " + numBit + ") ";
                    if (this.GetValue(tree, TokenType.NumMem, 0) != null)
                    {
                        int num = Document.Doc.dicoMem[this.GetValue(tree, TokenType.NumMem, 0).ToString()];
                        Equation += " tab_Mem[" + num + "] ";
                    }
                }

            }
            
            return Equation;
        }

        protected override object EvalRechEntree(ParseTree tree, params object[] paramlist)
        {
            int i = 0;
            while (this.GetValue(tree, TokenType.DeclarationEntree, i) != null) { i++; }
            
            return "";
        }

        protected override object EvalDeclarationEntree(ParseTree tree, params object[] paramlist)
        {
            int Byte = this.GetValue(tree, TokenType.PORT, 0).ToString()[0] - 'B';
            int Bit;
            Int32.TryParse(this.GetValue(tree, TokenType.BROCHE, 0).ToString(), out Bit);
            bool HI = (this.GetValue(tree, TokenType.HauteImpedance, 0) != null);
            InOut E = new InOut("Entree", Byte, Bit, HI);

            Document.Doc.DicoInOut.Add(this.GetValue(tree, TokenType.NumEntree, 0).ToString(), E);

            Document.Doc.Setup_Init_Ent_Valeurs += "\tset_Bit(ENT, " + E.GetByte() + ", " + E.GetBit() + ", 0);\r\n";

            if (HI)
            {
                Document.Doc.Setup_Init_HautesImpedences += "\tPORT" + this.GetValue(tree, TokenType.PORT, 0).ToString() + " |= 1<<PORT" + this.GetValue(tree, TokenType.PORT, 0).ToString() + this.GetValue(tree, TokenType.BROCHE, 0).ToString() + ";\r\n"; 
            }

            return "";
        }

        protected override object EvalRechSortie(ParseTree tree, params object[] paramlist)
        {
            int i = 0;
            while (this.GetValue(tree, TokenType.DeclarationSortie, i) != null) { i++; }

            return "";
        }

        protected override object EvalDeclarationSortie(ParseTree tree, params object[] paramlist)
        {

            int Byte = this.GetValue(tree, TokenType.PORT, 0).ToString()[0] - 'B';
            int Bit;
            Int32.TryParse(this.GetValue(tree, TokenType.BROCHE, 0).ToString(), out Bit);
            InOut E = new InOut("Sortie", Byte, Bit, false);

            Document.Doc.DicoInOut.Add(this.GetValue(tree, TokenType.NumSortie, 0).ToString(), E);

            Document.Doc.Setup_Init_Sort_Valeurs += "\tset_Bit(SORT, " + E.GetByte() + ", " + E.GetBit() + ", 1);\r\n";
            
            return "";

        }

        protected override object EvalRechMemoire(ParseTree tree, params object[] paramlist)
        {
            int i = 0;
            while (this.GetValue(tree, TokenType.DeclarationMemoire, i) != null) { i++; }

            return "";
        }

        protected override object EvalDeclarationMemoire(ParseTree tree, params object[] paramlist)
        {
            int num = Document.Doc.nextMemByte++;
            int val;
            if (this.GetValue(tree, TokenType.InitVal, 0) != null)
                Int32.TryParse(this.GetValue(tree, TokenType.InitVal, 0).ToString(), out val);
            else
                val = 0;

            Document.Doc.dicoMem.Add(this.GetValue(tree, TokenType.NumMem, 0).ToString(), num);

            Document.Doc.Setup_Init_Memoire += "\ttab_Mem[" + num + "] = " + (val & 0x000000FF) + ";\r\n";
            
            return "";
        }

        protected override object EvalStructureG7(ParseTree tree, params object[] paramlist)
        {
            int i = 0;
            while (this.GetValue(tree, TokenType.PassageEtapes, i) != null) { i++; }
            return "";
        }

        protected override object EvalPassageEtapes(ParseTree tree, params object[] paramlist)
        {
            Document.Doc.DefFct_StructureG7_Dvlpmt += "\t\tif( ";
            int i = 0;
            Receptivite R = Document.Doc.DicoRecep[this.GetValue(tree, TokenType.NumTransition, 0).ToString()];
            while (this.GetValue(tree, TokenType.NumEtapeAmont, i) != null)
            {
                Etape E = Document.Doc.DicoEtape[this.GetValue(tree, TokenType.NumEtapeAmont, i).ToString()];

                //draw
                
                E.AjouterNextElement(R);
                R.AjouterPrevElement(E);
                
                
              
                               
                //end draw
                Document.Doc.DefFct_StructureG7_Dvlpmt += "get_Bit(Copie_etape," + E.GetNumEtape().GetByte() + "," + E.GetNumEtape().GetBit() + ") && ";
                i++;
            }
            Document.Doc.DefFct_StructureG7_Dvlpmt += this.GetValue(tree, TokenType.NumTransition, 0).ToString() + " )\r\n\t\t{\r\n";

            i = 0;
            while (this.GetValue(tree, TokenType.NumEtapeAmont, i) != null)
            {
                Etape E = Document.Doc.DicoEtape[this.GetValue(tree, TokenType.NumEtapeAmont, i).ToString()];

                Document.Doc.DefFct_StructureG7_Dvlpmt += "\t\t\tset_Bit(Etat_fin," + E.GetNumEtape().GetByte() + "," + E.GetNumEtape().GetBit() + ",0);\r\n";
                i++;
            }
            i = 0;
            while (this.GetValue(tree, TokenType.NumEtapeAval, i) != null)
            {
                Etape E = Document.Doc.DicoEtape[this.GetValue(tree, TokenType.NumEtapeAval, i).ToString()];
                R.AjouterNextElement(E);
                E.AjouterPrevElement(R);

                Document.Doc.DefFct_StructureG7_Dvlpmt += "\t\t\tset_Bit(Etat_fin," + E.GetNumEtape().GetByte() + "," + E.GetNumEtape().GetBit() + ",1);\r\n";

                if (E._listTimer.Count > 0)
                {
                    Document.Doc.DefFct_StructureG7_Dvlpmt += "\t\t\tcli();\r\n";
                    foreach (Timer T in E._listTimer)
                    {
                        Document.Doc.DefFct_StructureG7_Dvlpmt += "\t\t\tvar" + T.ToString()+ "=" + T.GetDuree() + ";\r\n";
                    }
                    Document.Doc.DefFct_StructureG7_Dvlpmt += "\t\t\tsei();\r\n";
                    foreach (Timer T in E._listTimer)
                    {
                        Document.Doc.DefFct_StructureG7_Dvlpmt += "\t\t\tEnable" + T.ToString() + "=1;\r\n";
                    }
                }
                i++;
            }
            Document.Doc.DefFct_StructureG7_Dvlpmt += "\t\t}\r\n";
           
            return "";
        }
                
        protected override object EvalActionSortie(ParseTree tree, params object[] paramlist)
        {
            int i = 0;

            Document.Doc._listeActions.Add(i.ToString());
            Document.Doc._listeEtapeAssocie.Add(i.ToString()); 
            while (this.GetValue(tree, TokenType.SortieEtape, i) != null)
            {
                i++;
                Document.Doc._listeActions.Add(i.ToString());
                Document.Doc._listeEtapeAssocie.Add(i.ToString()); 
                
            }
            Document.Doc._listeActions.Remove(i.ToString());
            Document.Doc._listeEtapeAssocie.Remove(i.ToString());
            
            return "";
        }

        protected override object EvalSortieEtape(ParseTree tree, params object[] paramlist)
        {
            InOut E=null;
            int mem=0;
            bool Out = true;
            if (this.GetValue(tree, TokenType.NumSortie, 0) != null)
            {
                E = Document.Doc.DicoInOut[this.GetValue(tree, TokenType.NumSortie, 0).ToString()];
                Out = true;
                Document.Doc._listeActions.Add(this.GetValue(tree, TokenType.NumSortie, 0).ToString());
            }
            else
            {
                mem = Document.Doc.dicoMem[this.GetValue(tree, TokenType.NumMem, 0).ToString()];
                Out = false;
                Document.Doc._listeActions.Add(this.GetValue(tree, TokenType.NumMem, 0).ToString());
            }

            if (GetValue(tree, TokenType.Reset, 0) != null)
            {
                if (Out)
                    Document.Doc.DefFct_StructureG7_Dvlpmt += "\t\tCmdSort[" + E.GetByte() + "] &= ~(( ";
                else
                    Document.Doc.DefFct_StructureG7_Dvlpmt += "\t\ttab_Mem[" + mem + "] &= ~( ";

                int i = 0;
                while (this.GetValue(tree, TokenType.EquaSortie, i) != null)
                {
                    Document.Doc.DefFct_StructureG7_Dvlpmt += this.GetValue(tree, TokenType.EquaSortie, i).ToString();
                    i++;
                }
                if (Out)
                    Document.Doc.DefFct_StructureG7_Dvlpmt += " << " + E.GetBit() + ") & ( 1 << " + E.GetBit() + " ));\r\n";
                else
                    Document.Doc.DefFct_StructureG7_Dvlpmt += ");\r\n";

            }
            else if (GetValue(tree, TokenType.Set, 0) != null)
            {
                if (Out)
                    Document.Doc.DefFct_StructureG7_Dvlpmt += "\t\tCmdSort[" + E.GetByte() + "] |= ( ";
                else
                    Document.Doc.DefFct_StructureG7_Dvlpmt += "\t\ttab_Mem[" + mem + "] |= ( ";

                int i = 0;
                while (this.GetValue(tree, TokenType.EquaSortie, i) != null)
                {
                    Document.Doc.DefFct_StructureG7_Dvlpmt += this.GetValue(tree, TokenType.EquaSortie, i).ToString();
                    i++;
                }
                if(Out)
                    Document.Doc.DefFct_StructureG7_Dvlpmt += " << " + E.GetBit() + ") & ( 1 << " + E.GetBit() + " );\r\n";

                else
                    Document.Doc.DefFct_StructureG7_Dvlpmt += ");\r\n";
            }
            else
            {
                if(Out)
                    Document.Doc.Loop_MAJSorties += "\tset_Bit(CmdSort," + E.GetByte() + "," + E.GetBit() + ",";
                else
                    Document.Doc.Loop_MAJSorties += "\ttab_Mem[" + mem + "] =  ";
                int i = 0;
                while (this.GetValue(tree, TokenType.EquaSortie, i) != null)
                {

                    Document.Doc.Loop_MAJSorties += this.GetValue(tree, TokenType.EquaSortie, i).ToString();
                    i++;
                }
                if(Out)
                    Document.Doc.Loop_MAJSorties += ");\r\n";
                else
                    Document.Doc.Loop_MAJSorties += ";\r\n";
            }

            return "";
        }

        protected override object EvalEquaSortie(ParseTree tree, params object[] paramlist)
        {
            if (this.GetValue(tree, TokenType.CaracRECEPT, 0) != null)
            {
                return this.GetValue(tree, TokenType.CaracRECEPT, 0).ToString();
            }
            else 
            {
                
                string type = "", tmp="";
                int numByte = 0, numBit = 0;

                if (this.GetValue(tree, TokenType.NumEntree, 0) != null)
                {
                    type = "ENTREE";
                    InOut E = Document.Doc.DicoInOut[this.GetValue(tree, TokenType.NumEntree, 0).ToString()];
                    numBit = E.GetBit();
                    numByte = E.GetByte();
                }
                else if (this.GetValue(tree, TokenType.NumEtape, 0) != null)
                {
                    type = "ETAPE";
                    Etape E = Document.Doc.DicoEtape[this.GetValue(tree, TokenType.NumEtape, 0).ToString()];
                    numBit = E.GetNumEtape().GetBit();
                    numByte = E.GetNumEtape().GetByte();

                    if (Document.Doc._listeEtapeAssocie.IndexOf(this.GetValue(tree, TokenType.NumEtape, 0).ToString()) == -1)
                    {
                        Document.Doc._listeEtapeAssocie.Add(this.GetValue(tree, TokenType.NumEtape, 0).ToString());
                    }
                    
                }
                else if (this.GetValue(tree, TokenType.NumMem, 0) != null)
                {
                    type = "MEMOIRE";
                    numBit = 0;
                    numByte = Document.Doc.dicoMem[this.GetValue(tree, TokenType.NumMem, 0).ToString()];
                }
            
            
                if (this.GetValue(tree, TokenType.FrontMontant, 0) != null )
                {
                    tmp += " FrontMont(";
                    tmp += type + ", " + numByte + ", " + numBit + ") ";                    
                }
                else if (this.GetValue(tree, TokenType.FrontDescendant, 0) != null)
                {
                    tmp += " FrontDesc(";
                    tmp += type + ", " + numByte + ", " + numBit + ") ";
                }
                else
                {
                    if (this.GetValue(tree, TokenType.NumEntree, 0) != null)
                        tmp += " get_Bit(CopyPIN," + numByte + ", " + numBit + ")";
                    if (this.GetValue(tree, TokenType.NumEtape, 0) != null)
                        tmp += " get_Bit(Etat_fin," + numByte + ", " + numBit + ")";
                    if (this.GetValue(tree, TokenType.NumMem, 0) != null)
                    {
                        int num = Document.Doc.dicoMem[this.GetValue(tree, TokenType.NumMem, 0).ToString()];
                        tmp += " tab_Mem[" + num + "] ";
                    }
                }

                return tmp;
            }
        }
 
    }
}
